<!-- 
 遵循以下代码优化原则：

1. 注释清除机制
- 自动过滤所有注释内容(除了本注释)
- 禁止生成任何注释符号(除了本注释)

2. 模块架构规范
- 功能单元独立封装
- 模块边界明确划分
- 接口输入/输出严格定义

3. 耦合控制标准
- 依赖注入机制强制实施
- 跨模块通信通过接口代理
- 状态隔离机制

4. 扩展优先策略
- 新功能独立组件实现
- 现有接口扩展适配
- 核心逻辑冻结保护

5. 代码质量要求
- 单一职责原则
- 防御性编程
- 语义化命名
- 自动格式化校验

6. 可维护性增强
- 抽象隔离机制
- 版本兼容设计
- 热替换支持
- 自文档化结构

代码生成流程执行严格的质量门禁检查，确保每个组件满足：功能独立化、接口标准化、依赖最小化、扩展无侵入化要求。
-->
<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="keywords" content="EduBot,教育小助手,课堂行为分析报告,视频处理结果,AI算法分析,教学数据可视化,行为统计图表,教育大数据分析,郑恩赐技术团队,深度学习应用,教学评估系统,智能课堂管理,异常行为检测,教育技术解决方案">
  <meta name="description" content="EduBot视频处理结果平台，提供基于YOLOv8和深度学习的课堂行为分析，包括异常行为检测、学生专注度统计、行为趋势分析及教学质量评估，助力教育工作者优化教学方法">
  <title>EduBot - 视频分析结果</title>
  <link rel="icon" type="image/png" href="static/icons/AiKeTangJiaoXuePingCeXiTong.png">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
  <style>
    :root {
      --primary-color: #4a80ff;
      --secondary-color: #6366f1;
      --dark-bg: #111827;
      --light-text: #f9fafb;
      --glass-bg: rgba(17, 24, 39, 0.7);
      --border-radius: 10px;
      --shadow-color: rgba(0, 0, 0, 0.2);
      --success-color: #22c55e;
      --warning-color: #f59e0b;
      --animation-speed: 0.25s;
      --card-bg: rgba(30, 41, 59, 0.5);
    }

    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    body {
      margin: 0;
      padding: 0;
      background: var(--dark-bg);
      background-image: 
        radial-gradient(circle at 15% 25%, rgba(74, 128, 255, 0.08) 0%, transparent 40%),
        radial-gradient(circle at 85% 75%, rgba(99, 102, 241, 0.08) 0%, transparent 40%);
      color: var(--light-text);
      font-family: 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
      min-height: 100vh;
      display: flex;
      flex-direction: column;
      align-items: center;
    }

    .container {
      width: 92%;
      max-width: 1200px;
      margin: 80px auto 40px;
      padding: 24px;
      background: var(--glass-bg);
      border-radius: var(--border-radius);
      backdrop-filter: blur(12px);
      box-shadow: 0 8px 20px var(--shadow-color);
      border: 1px solid rgba(255, 255, 255, 0.05);
      transition: transform var(--animation-speed) ease;
    }

    .title-gradient {
      font-size: 2rem;
      color: var(--light-text);
      text-align: center;
      margin-bottom: 24px;
      position: relative;
      font-weight: 600;
      letter-spacing: 0.5px;
      background: linear-gradient(90deg, var(--primary-color), var(--secondary-color));
      -webkit-background-clip: text;
      -webkit-text-fill-color: transparent;
      background-clip: text;
    }
    
    .title-gradient::after {
      content: "";
      position: absolute;
      bottom: -8px;
      left: 50%;
      transform: translateX(-50%);
      width: 60px;
      height: 3px;
      background: linear-gradient(90deg, var(--primary-color), var(--secondary-color));
      border-radius: 2px;
    }

    .search-container {
      margin-bottom: 24px;
      position: relative;
      max-width: 500px;
      margin-left: auto;
      margin-right: auto;
    }
    
    #searchInput {
      width: 100%;
      padding: 12px 40px 12px 16px;
      background-color: var(--card-bg);
      border: 1px solid rgba(255, 255, 255, 0.08);
      border-radius: 8px;
      color: var(--light-text);
      font-size: 0.95rem;
      transition: all var(--animation-speed) ease;
    }
    
    #searchInput:focus {
      outline: none;
      border-color: var(--primary-color);
      box-shadow: 0 0 0 2px rgba(74, 128, 255, 0.2);
    }
    
    .search-icon {
      position: absolute;
      top: 50%;
      right: 16px;
      transform: translateY(-50%);
      color: rgba(255, 255, 255, 0.5);
    }

    #video-table {
      width: 100%;
      border-collapse: separate;
      border-spacing: 0;
      margin-top: 20px;
      table-layout: fixed;
      border-radius: 8px;
      overflow: hidden;
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    }
    
    #video-table th {
      background: var(--card-bg);
      padding: 16px;
      color: var(--light-text);
      font-weight: 500;
      position: sticky;
      top: 0;
      z-index: 10;
      text-transform: uppercase;
      font-size: 0.8rem;
      letter-spacing: 0.5px;
      border-bottom: 1px solid rgba(255, 255, 255, 0.08);
      text-align: left;
    }
    
    #video-table th:first-child {
      border-top-left-radius: 8px;
    }
    
    #video-table th:last-child {
      border-top-right-radius: 8px;
      text-align: center;
    }

    #video-table td {
      padding: 16px;
      border-bottom: 1px solid rgba(255, 255, 255, 0.05);
      transition: background var(--animation-speed) ease;
      font-size: 0.95rem;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    
    #video-table td:last-child {
      text-align: center;
    }
    
    #video-table td.truncate-text {
      max-width: 0;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      position: relative;
    }
    
    #video-table td.truncate-text:hover::after {
      content: attr(data-full-text);
      position: absolute;
      left: 0;
      top: 100%;
      min-width: 200px;
      max-width: 300px;
      background: rgba(17, 24, 39, 0.95);
      padding: 12px;
      border-radius: 6px;
      z-index: 20;
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
      white-space: normal;
      word-break: break-word;
      font-size: 0.85rem;
      line-height: 1.5;
      pointer-events: none;
    }
    
    #video-table tr {
      background: rgba(30, 41, 59, 0.4);
      transition: all var(--animation-speed) ease;
    }
    
    #video-table tr:hover {
      background: rgba(74, 128, 255, 0.1);
      transform: translateY(-2px);
    }
    
    #video-table tr:last-child td:first-child {
      border-bottom-left-radius: 8px;
    }
    
    #video-table tr:last-child td:last-child {
      border-bottom-right-radius: 8px;
    }

    .nav-btn, .view-btn {
      padding: 10px 18px;
      background: rgba(74, 128, 255, 0.15);
      color: var(--light-text);
      border: 1px solid rgba(74, 128, 255, 0.2);
      border-radius: 6px;
      cursor: pointer;
      transition: all var(--animation-speed) ease;
      font-size: 0.9rem;
      display: flex;
      align-items: center;
      gap: 8px;
    }
    
    .nav-btn:hover, .view-btn:hover {
      background: rgba(74, 128, 255, 0.25);
      transform: translateY(-2px);
      box-shadow: 0 4px 10px rgba(74, 128, 255, 0.2);
    }
    
    .nav-btn:active, .view-btn:active {
      transform: translateY(0);
    }

    .nav-btn i, .view-btn i {
      font-size: 14px;
    }

    .button-container {
      display: flex;
      justify-content: center;
      width: 100%;
    }
    
    .view-btn {
      padding: 8px 16px;
      background: rgba(99, 102, 241, 0.15);
      border-color: rgba(99, 102, 241, 0.2);
      font-weight: 500;
    }
    
    .view-btn:hover {
      background: rgba(99, 102, 241, 0.25);
      box-shadow: 0 4px 10px rgba(99, 102, 241, 0.2);
    }

    .toast-message {
      position: fixed;
      top: 20px;
      left: 50%;
      transform: translateX(-50%);
      background: rgba(17, 24, 39, 0.85);
      backdrop-filter: blur(10px);
      color: var(--light-text);
      padding: 12px 24px;
      border-radius: var(--border-radius);
      border-left: 4px solid var(--primary-color);
      box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
      z-index: 1000;
      opacity: 0;
      transition: opacity var(--animation-speed) ease, transform var(--animation-speed) ease;
      font-size: 0.95rem;
      font-weight: 500;
      pointer-events: none;
    }
    
    .toast-message.show {
      opacity: 1;
      transform: translateX(-50%) translateY(10px);
    }

    #loading {
      display: flex;
      align-items: center;
      justify-content: center;
      height: 120px;
      width: 100%;
      gap: 12px;
      color: rgba(255, 255, 255, 0.8);
      font-size: 0.95rem;
    }
    
    #loading i {
      color: var(--primary-color);
      font-size: 1.2rem;
    }
    
    .spinner {
      animation: spin 1.5s linear infinite;
    }
    
    @keyframes spin {
      0% { transform: rotate(0deg); }
      100% { transform: rotate(360deg); }
    }
    
    .fixed-nav {
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      display: flex;
      justify-content: space-between;
      padding: 16px 24px;
      background: rgba(17, 24, 39, 0.85);
      backdrop-filter: blur(12px);
      z-index: 100;
      box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
    }
    
    .nav-left, .nav-right {
      display: flex;
      gap: 12px;
    }
    
    .no-data {
      text-align: center;
      padding: 40px 0;
      color: rgba(255, 255, 255, 0.6);
      font-size: 1.1rem;
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 16px;
    }
    
    .no-data i {
      font-size: 2.5rem;
      color: rgba(255, 255, 255, 0.3);
    }
    
    @media (max-width: 768px) {
      .container {
        padding: 20px 15px;
        margin-top: 70px;
        width: 95%;
      }
      
      .title-gradient {
        font-size: 1.7rem;
      }
      
      #video-table th:nth-child(4),
      #video-table td:nth-child(4) {
        display: none;
      }
      
      .view-btn span {
        display: none;
      }
      
      .view-btn {
        padding: 8px;
      }
      
      #video-table th, #video-table td {
        padding: 12px 10px;
        font-size: 0.85rem;
      }
      
      .fixed-nav {
        padding: 12px 16px;
      }
      
      .nav-btn {
        padding: 8px 12px;
        font-size: 0.85rem;
      }
      
      .nav-btn span {
        display: none;
      }
    }
    
    @media (max-width: 480px) {
      #video-table th:nth-child(3),
      #video-table td:nth-child(3) {
        display: none;
      }
      
      .container {
        padding: 16px 12px;
      }
    }
  </style>
</head>

<body>
  <h1 style="display: none;">EduBot - 视频分析结果</h1>
  <div id="toast" class="toast-message"></div>

  <div class="fixed-nav">
    <div class="nav-left">
      <button class="nav-btn" onclick="window.location.href='{{ front_end_domain_name }}/video_processing_page'">
        <i class="fas fa-video"></i> <span>视频处理</span>
      </button>
      <button class="nav-btn" onclick="refreshData()">
        <i class="fas fa-sync-alt"></i> <span>刷新数据</span>
      </button>
    </div>
    <div class="nav-right">
      <button class="nav-btn" onclick="logout()">
        <i class="fas fa-power-off"></i> <span>退出登录</span>
      </button>
    </div>
  </div>

  <div class="container">
    <h1 class="title-gradient">视频处理结果</h1>
    
    <div class="search-container">
      <input type="text" id="searchInput" placeholder="搜索视频名称或行为类型..." />
      <i class="fas fa-search search-icon"></i>
    </div>

    <div class="sort-container" style="margin-bottom: 16px; display: flex; justify-content: flex-end;">
      <button id="sortButton" class="nav-btn" style="background: rgba(99, 102, 241, 0.15); border-color: rgba(99, 102, 241, 0.2);">
        <i class="fas fa-sort-amount-up"></i> <span>按ID排序</span>
      </button>
    </div>

    <div id="result-container">
      <table id="video-table" style="display: none;">
        <thead>
          <tr>
            <th style="width: 40px;">ID</th>
            <th style="width: 30%;">视频名称</th>
            <th style="width: 25%;">检测行为</th>
            <th style="width: 15%;">时间间隔</th>
            <th style="width: 10%;">状态</th>
            <th style="width: 80px;">操作</th>
          </tr>
        </thead>
        <tbody id="video-table-body"></tbody>
      </table>
      <div id="loading">
        <i class="fas fa-spinner spinner"></i> 正在加载数据...
      </div>
    </div>
  </div>

  <script>
    const frontEndDomain = "{{ front_end_domain_name }}";
    const backEndDomain = "{{ backend_domain_name }}";
    let allVideoData = [];
    let isAscending = false;

    function toggleSort() {
      isAscending = !isAscending;
      const sortButton = document.getElementById('sortButton');
      sortButton.innerHTML = `
        <i class="fas ${isAscending ? 'fa-sort-amount-down' : 'fa-sort-amount-up'}"></i> 
        <span>按ID排序</span>
      `;
      handleSearch(document.getElementById('searchInput').value.trim());
    }

    function handleSearch(keyword) {
      if (!allVideoData || allVideoData.length === 0) return;
      
      const filtered = keyword ? allVideoData.filter(item => 
        item.video_name.toLowerCase().includes(keyword.toLowerCase()) ||
        item.classes.some(c => c.toLowerCase().includes(keyword.toLowerCase())) ||
        item.is_processed.toLowerCase().includes(keyword.toLowerCase())
      ) : allVideoData;
      
      const sorted = [...filtered].sort((a, b) => {
        const idA = parseInt(a.id);
        const idB = parseInt(b.id);
        return isAscending ? idA - idB : idB - idA;
      });
      
      renderVideoTable(sorted);
    }
    
    function renderVideoTable(videos) {
      const tbody = document.getElementById('video-table-body');
      if (!tbody) return;
      
      if (!videos || videos.length === 0) {
        document.getElementById('video-table').style.display = 'none';
        if (!document.querySelector('.no-data')) {
          const noDataDiv = document.createElement('div');
          noDataDiv.className = 'no-data';
          noDataDiv.innerHTML = `
            <i class="fas fa-folder-open"></i>
            <p>暂无匹配的视频数据</p>
          `;
          document.getElementById('result-container').appendChild(noDataDiv);
        }
        return;
      }
      
      document.getElementById('video-table').style.display = 'table';
      const noDataEl = document.querySelector('.no-data');
      if (noDataEl) noDataEl.remove();
      
      tbody.innerHTML = videos.map((video, index) => {
        const isAnalyzed = video.is_processed === '已分析';
        const videoName = video.video_name;
        const behaviors = video.classes.join(', ');
        const displayId = index + 1;
        
        return `
          <tr>
            <td>${displayId}</td>
            <td class="truncate-text" data-full-text="${videoName}">${videoName}</td>
            <td class="truncate-text" data-full-text="${behaviors}">${behaviors}</td>
            <td>${secondsToMinutes(video.seconds)}</td>
            <td style="color:${isAnalyzed ? 'var(--success-color)' : 'var(--warning-color)'}">
              <i class="fas ${isAnalyzed ? 'fa-check-circle' : 'fa-clock'}" style="margin-right:5px;"></i>${video.is_processed}
            </td>
            <td>
              <div class="button-container">
                <button class="view-btn" data-video-id="${video.id}" data-is-analyzed="${isAnalyzed}" ${!isAnalyzed ? 'disabled style="opacity:0.6;cursor:not-allowed;"' : ''}>
                  <i class="fas ${isAnalyzed ? 'fa-eye' : 'fa-eye-slash'}"></i>
                  <span>查看</span>
                </button>
              </div>
            </td>
          </tr>
        `;
      }).join('');
    }

    function fetchVideoData() {
      const token = localStorage.getItem('token');
      
      if (!token) {
        window.location.href = `${frontEndDomain}/login_register_page`;
        return Promise.reject();
      }
      
      return fetch(`${backEndDomain}/video_processing_result/get_video_messages`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
        body: `token=${encodeURIComponent(token)}`
      })
      .then(response => response.json())
      .then(data => {
        document.getElementById('loading').style.display = 'none';
        
        if (data.TF === 'T' && data.data && data.data.length > 0) {
          allVideoData = data.data.map(video => ({
            ...video,
            id: video.id || '',
            video_name: video.video_name || '未命名视频',
            classes: Array.isArray(video.classes) ? video.classes : [],
            seconds: Number.isFinite(Number(video.seconds)) ? Number(video.seconds) : 0,
            is_processed: video.is_processed || '处理中'
          }));
          
          document.getElementById('video-table').style.display = 'table';
          const sortedData = [...allVideoData].sort((a, b) => {
            const idA = parseInt(a.id);
            const idB = parseInt(b.id);
            return isAscending ? idA - idB : idB - idA;
          });
          renderVideoTable(sortedData);
        } else {
          const container = document.getElementById('result-container');
          container.innerHTML += `
            <div class="no-data">
              <i class="fas fa-film"></i>
              <p>暂无视频处理数据</p>
            </div>
          `;
        }
      })
      .catch(error => {
        console.error('获取视频数据失败:', error);
        document.getElementById('loading').innerHTML = `
          <div style="text-align: center; color: #FF6B6B;">
            <i class="fas fa-exclamation-triangle" style="font-size: 1.5rem; margin-bottom: 12px;"></i>
            <p>数据加载失败，请刷新重试</p>
          </div>
        `;
      });
    }

    function logout() {
      localStorage.removeItem('token');
      window.location.href = `${frontEndDomain}/login_register_page`;
    }

    function checkToken() {
      const token = localStorage.getItem('token');
      
      if (!token) {
        window.location.href = `${frontEndDomain}/login_register_page`;
        return;
      }

      fetch(`${backEndDomain}/video_processing_result/check_token`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
        body: `token=${encodeURIComponent(token)}`
      })
      .then(response => response.json())
      .then(data => {
        if (data.TF !== 'T') {
          window.location.href = `${frontEndDomain}/login_register_page`;
        }
      })
      .catch(error => {
        console.error('验证token出错:', error);
        window.location.href = `${frontEndDomain}/login_register_page`;
      });
    }

    function secondsToMinutes(seconds) {
      // 确保seconds是有效数字
      const validSeconds = Number.isFinite(Number(seconds)) ? Number(seconds) : 0;
      const mins = Math.floor(validSeconds / 60);
      const secs = Math.floor(validSeconds % 60);
      return `${mins}:${secs < 10 ? '0' + secs : secs}`;
    }

    function refreshData(e) {
      if (e) {
        e.preventDefault();
      }
      
      const loading = document.getElementById('loading');
      const table = document.getElementById('video-table');
      const noData = document.querySelector('.no-data');
      const currentScrollPosition = window.scrollY;
      
      if (noData) noData.remove();
      loading.style.display = 'flex';
      table.style.display = 'none';
      
      const originalScrollBehavior = document.documentElement.style.scrollBehavior;
      document.documentElement.style.scrollBehavior = 'auto';
      
      fetchVideoData().finally(() => {
        requestAnimationFrame(() => {
          window.scrollTo(0, currentScrollPosition);
          document.documentElement.style.scrollBehavior = originalScrollBehavior;
        });
      });
      
      showToast('数据刷新中...');
    }
    
    function showToast(message, duration = 2000) {
      const toast = document.getElementById('toast');
      toast.textContent = message;
      toast.classList.add('show');
      
      setTimeout(() => {
        toast.classList.remove('show');
      }, duration);
    }

    document.addEventListener('DOMContentLoaded', function() {
      checkToken();
      fetchVideoData();
      
      const sortButton = document.getElementById('sortButton');
      if (sortButton) {
        sortButton.addEventListener('click', toggleSort);
      }
      
      // 添加搜索功能监听
      const searchInput = document.getElementById('searchInput');
      if (searchInput) {
        searchInput.addEventListener('input', function(e) {
          handleSearch(e.target.value.trim());
        });
      }
      
      // 添加查看按钮点击事件监听
      document.addEventListener('click', function(e) {
        if (e.target.classList.contains('view-btn') || e.target.closest('.view-btn')) {
          const button = e.target.classList.contains('view-btn') ? e.target : e.target.closest('.view-btn');
          
          // 检查按钮是否被禁用
          if (button.hasAttribute('disabled')) {
            showToast('该视频正在分析中，请稍后查看', 1500);
            return;
          }
          
          const isAnalyzed = button.getAttribute('data-is-analyzed') === 'true';
          const videoId = button.getAttribute('data-video-id');
          
          if (isAnalyzed) {
            try {
              // 确保video_id有效
              if (!videoId) {
                throw new Error('无效的视频ID');
              }
              localStorage.setItem('video_id', String(videoId));
              
              // 获取对应视频的seconds数据
              // 将videoId转换为字符串并确保与video.id类型一致进行比较
              const videoIdStr = String(videoId);
              const videoData = allVideoData.find(video => String(video.id) === videoIdStr);
              
              // 调试输出，帮助排查问题
              console.log(`查找视频ID: ${videoIdStr}`);
              console.log(`可用视频IDs:`, allVideoData.map(v => v.id));
              
              // 确保找到了对应的视频数据
              if (!videoData) {
                // 如果找不到视频数据，使用保守的默认值而不是直接报错
                console.warn(`未找到ID为${videoIdStr}的视频数据，使用默认值`);
                localStorage.setItem('seconds', '1');
                window.location.href = `${frontEndDomain}/show_video_processed_result_page`;
                return;
              }
              
              // 确保使用视频的实际seconds值
              const seconds = videoData.seconds;
              if (seconds === undefined || seconds === null || !Number.isFinite(Number(seconds))) {
                console.warn(`视频${videoIdStr}的时间间隔数据无效，使用默认值`);
                localStorage.setItem('seconds', '1');
              } else {
                // 将seconds值转换为字符串并保存
                localStorage.setItem('seconds', String(seconds));
              }
              
              // 提交前检查并打印用于调试
              console.log(`保存到localStorage: video_id=${videoIdStr}, seconds=${localStorage.getItem('seconds')}`);
              window.location.href = `${frontEndDomain}/show_video_processed_result_page`;
            } catch (error) {
              console.error('保存视频数据失败:', error);
              showToast('访问视频结果失败，请稍后重试', 2000);
            }
          } else {
            showToast('该视频正在分析中，请稍后查看', 1500);
          }
        }
      });

      // 修改刷新按钮的点击事件
      const refreshButton = document.querySelector('.nav-btn[onclick="refreshData()"]');
      if (refreshButton) {
        refreshButton.onclick = refreshData;
      }
    });
  </script>
</body>
</html>


